package br.com.mubi.review;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.UploadedFile;

import br.com.mubi.comentario.Comentario;
import br.com.mubi.comentario.ComentarioDAO;
import br.com.mubi.usuario.Usuario;
import br.com.mubi.usuario.UsuarioDAO;
import br.com.mubi.util.DAOFactory;
import br.com.mubi.util.FacesUtil;
import br.com.mubi.util.HibernateUtil;

public class FilmeRN {
	//Filme
	private Filme filme;
	private FilmeDAO filmeDAO;
	private int genero;
	
	//usuario
	private Usuario usuario;
	private UsuarioDAO usuarioDAO;
	private String loginUsuarioAtual;
	private String nomeUsuario;
	
	//Comentario
	private Comentario comentario;
	private ComentarioDAO comentarioDAO;
	private long idFilme;
	private String comentarioFilme;
	
	//Lista de comentario
	private List<Comentario> listaComentariosFilme;

	//Rating
	private NotaDAO notaDAO;
	private String notaMedia;
	private Integer notaVoto;
	private boolean votou;
	
	//listas de filmes
	private List<Filme> listaFilmes;
	private List<Filme> listaFilmesPesquisa;
	
	//Inclusao de filmes
	private boolean continuacao;
	
	//pesquisa
	private String textoPesquisa;
		
	//Salvar Imagem
	private UploadedFile arquivoImagem;
	private static final String dirImagem = System.getProperty("user.home").replace("\\", "/") + "/Mubi/imagens/";
	private StreamedContent imagemCarregada;
	
	public FilmeRN() {
		filme = new Filme();
		filmeDAO = DAOFactory.criarFilmeDAO();
		usuarioDAO = DAOFactory.criarUsuarioDAO();
		notaDAO = DAOFactory.criarNotaDAO();
		comentarioDAO = DAOFactory.criarComentarioDAO();
		loginUsuarioAtual = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser(); 
		genero = 0;
		notaVoto = 0;
		notaMedia = "0";
		recuperarNomeUsuario();
	}
	
	private void recuperarNomeUsuario() {		
		usuarioDAO.buscarPorLogin(loginUsuarioAtual);
		usuario = usuarioDAO.buscarPorLogin(loginUsuarioAtual);	
		nomeUsuario = usuario.getNome();
	}
	
	public boolean continuarInclusao(){
		if(filme.getAnoLancamento() == 0 || filme.getClassificacao().isEmpty() || filme.getDirecao().isEmpty() || filme.getDuracao() == 0 
				|| filme.getGenero().isEmpty() || filme.getProdutora().isEmpty() || filme.getTituloBrasil().isEmpty() || filme.getTituloOriginal().isEmpty()){
			return continuacao;
		} else {
			return continuacao = true;
		}
	}
	
	public boolean validarInclusao(FacesContext context) {
		if(filme.getNomeImagem() != null) {
			if(filme.getLinkVideo().isEmpty() || filme.getSinopse().isEmpty()) {
				FacesUtil.addGrowlMessage(context, "Favor preencher todos os campos.", FacesMessage.SEVERITY_WARN);
				return false;
			}	
			
			if(this.filme.getId() == 0) {
				List<Filme> listaFilmes = this.filmeDAO.listar();
				for(Filme f : listaFilmes) {
					if(f.getTituloBrasil().equalsIgnoreCase(this.filme.getTituloBrasil().trim())) {
						FacesUtil.addGrowlMessage(context, "Já foi cadastrado um filme com este nome.", FacesMessage.SEVERITY_WARN);
						return false;
						
					} else if(f.getTituloOriginal().equalsIgnoreCase(this.filme.getTituloOriginal().trim())) {
						FacesUtil.addGrowlMessage(context, "Já foi cadastrado um filme com este nome.", FacesMessage.SEVERITY_WARN);
						return false;
					}
				}
			}
			return true;
		} else {
			FacesUtil.addGrowlMessage(context, "Selecione uma imagem.", FacesMessage.SEVERITY_WARN);
		}
		return false;
	}
	
	private void gravarArquivo(String caminho) throws IOException {
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(caminho);
			fos.write(arquivoImagem.getContents());
		} finally {
			if(fos != null)
				fos.close();
		}
	}
	
	public void fileUpload(FacesContext facesContext) {
		try {
			File caminho = new File(dirImagem);
			caminho.mkdirs();
			gravarArquivo(dirImagem + filme.getNomeImagem());
			
		} catch(Exception exception) {
			FacesUtil.addGrowlMessage(facesContext, "Erro no envio do arquivo.");
		}
	}
	
	public void tratarLinkVideo() {
		String[] link = filme.getLinkVideo().split("&");
		filme.setLinkVideo(link[0].replace("watch?", "").replace("=", "/"));
	}
	
	public void excluirReview(FacesContext context) {
		try {
			this.filme.getNota();
			DAOFactory.beginTransaction();			
			filmeDAO.excluir(this.filme);
			DAOFactory.commitTransaction();
			FacesUtil.addGrowlMessage(context, "Resenha excluída com sucesso.");
			listarTodosFilmesUsuario();
		} catch(HibernateException e) {
			e.printStackTrace();
			FacesUtil.addGrowlMessage(context, "Não foi possível excluir a resenha.", FacesMessage.SEVERITY_ERROR);
			DAOFactory.clearSession();
		}
	}
	
	public void salvarReview(FacesContext context) {
		try{
			DAOFactory.beginTransaction();			
			this.filme.setTituloBrasil(this.filme.getTituloBrasil().trim());
			this.filme.setTituloOriginal(this.filme.getTituloOriginal().trim());
			
			if(this.filme.getId() == 0) {
				this.usuario = this.usuarioDAO.buscarPorLogin(this.loginUsuarioAtual);
				this.filme.setUsuario(this.usuario);
				this.filme.setDataInclusao(new Date());
				this.filmeDAO.salvar(this.filme);
			} else {
				this.filmeDAO.atualizar(this.filme);
			}
			DAOFactory.commitTransaction();
		} catch(HibernateException e) {
			DAOFactory.clearSession();
		}
	}
	
	private void carregarImagem() {
		InputStream stream;
		try {
			stream = new FileInputStream(dirImagem + filme.getNomeImagem());
			imagemCarregada = new DefaultStreamedContent(stream);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public String listarTodosFilmesUsuario() {
		DAOFactory.clearSession();		
		usuarioDAO.buscarPorLogin(loginUsuarioAtual);
		usuario = usuarioDAO.buscarPorLogin(loginUsuarioAtual);		
		filme = new Filme();
		listaFilmes = usuario.getFilme();
		return "/restrito/meusFilmes.jsf";
	}
	
	@SuppressWarnings("unchecked")
	public void pesquisarFilmes() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		Criteria criteria = session.createCriteria(Filme.class);
		if(genero != 0) {
			criteria.add(Restrictions.eq("genero", String.valueOf(genero)));
		}
		criteria.add(Restrictions.like("tituloBrasil", textoPesquisa));
		listaFilmesPesquisa = criteria.list();
		transaction.commit();
		session.close();
	}
	
	public String exibirFIlmeSelecionado() {
		carregarImagem();
		calcularMedia();
		this.votou = false;
		this.comentarioFilme = "";
		listarComentariosFilme(filme.getId());
		return "/restrito/review.jsf";
	}
	
	public String listarFilmesIncluidosHoje() {
		filme = new Filme();
		textoPesquisa = "";
		pesquisarFilmesHoje();
		return "/restrito/principal.jsf";
	}
	
	@SuppressWarnings("unchecked")
	public void pesquisarFilmesHoje() {
		Session session = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			Transaction transaction = session.beginTransaction();
			Criteria criteria = session.createCriteria(Filme.class);
			
			Calendar calendar = new GregorianCalendar();
			calendar.setTime(new Date());
			calendar.set(Calendar.HOUR, 0);
			calendar.set(Calendar.MINUTE, 0);
			calendar.set(Calendar.SECOND, 0);
			calendar.set(Calendar.MILLISECOND, 0);
			
			criteria.add(Restrictions.eq("dataInclusao", calendar.getTime()));
			listaFilmesPesquisa = criteria.list();
			transaction.commit();
		} finally {
			if(session != null) {
				session.close();
			}
		}
	}
	
	public void salvarNota() {
		Nota nota = new Nota();
		nota.setFilme(this.filme);
		nota.setNota(this.notaVoto);
		try{			
			DAOFactory.beginTransaction();			
			this.notaDAO.salvar(nota);
			DAOFactory.commitTransaction();			
		} catch(HibernateException e) {
			DAOFactory.clearSession();
		}
	}

	public void calcularMedia() {
		List<Nota> listaNota = this.notaDAO.listarPorFilmeId(this.filme.getId());
		double media = 0;
		this.notaMedia = "0";
		this.notaVoto = 0;
		
		if(listaNota.size() > 0) {	
			
			for(Nota nota : listaNota) {
				media += nota.getNota();
			}			
			
			media = media/listaNota.size();
			
			NumberFormat nf = NumberFormat.getInstance();
			nf.setMaximumFractionDigits(2);
			nf.setMinimumFractionDigits(1);
			this.notaMedia = nf.format(media);			
			this.notaVoto = (int) Math.round(media);
		}
	}
	
	@SuppressWarnings("unchecked")
	public void listarComentariosFilme(long id) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		Criteria criteria = session.createCriteria(Comentario.class);
		listaComentariosFilme = criteria.add(Restrictions.eq("idFilme", id)).list();
	}
	
	public void salvarComentarioFilme(){
		if(!this.comentarioFilme.isEmpty()) {
			comentario = new Comentario();
			DAOFactory.getSession();
			DAOFactory.beginTransaction();
			comentario.setIdFilme(filme.getId());
			comentario.setComentarioFilme(comentarioFilme);
			comentario.setNomeUsuario(loginUsuarioAtual);
			comentarioDAO.salvar(comentario);
			DAOFactory.commitTransaction();
			this.listaComentariosFilme.add(comentario);
			this.comentarioFilme = "";
		}
	}
	
	public void voltar(){
		continuacao = false;
	}

	public Filme getFilme() {
		return filme;
	}

	public void setFilme(Filme filme) {
		this.filme = filme;
	}

	public boolean isContinuacao() {
		return continuacao;
	}

	public void setContinuacao(boolean continuacao) {
		this.continuacao = continuacao;
	}

	public List<Filme> getListaFilmes() {
		return listaFilmes;
	}

	public void setListaFilmes(List<Filme> listaFilmes) {
		this.listaFilmes = listaFilmes;
	}

	public int getGenero() {
		return genero;
	}

	public void setGenero(int genero) {
		this.genero = genero;
	}

	public String getTextoPesquisa() {
		return textoPesquisa;
	}

	public void setTextoPesquisa(String textoPesquisa) {
		this.textoPesquisa = textoPesquisa;
	}

	public List<Filme> getListaFilmesPesquisa() {
		return listaFilmesPesquisa;
	}

	public void setListaFilmesPesquisa(List<Filme> listaFilmesPesquisa) {
		this.listaFilmesPesquisa = listaFilmesPesquisa;
	}

	public UploadedFile getArquivoImagem() {
		return arquivoImagem;
	}

	public void setArquivoImagem(UploadedFile arquivoImagem) {
		this.arquivoImagem = arquivoImagem;
	}
	
	public StreamedContent getImagemCarregada() {
		return imagemCarregada;
	}

	public void setImagemCarregada(StreamedContent imagemCarregada) {
		this.imagemCarregada = imagemCarregada;
	}

	public String getNomeUsuario() {
		return nomeUsuario;
	}

	public void setNomeUsuario(String nomeUsuario) {
		this.nomeUsuario = nomeUsuario;
	}

	public String getNotaMedia() {
		return notaMedia;
	}

	public void setNotaMedia(String notaMedia) {
		this.notaMedia = notaMedia;
	}

	public Integer getNotaVoto() {
		return notaVoto;
	}

	public void setNotaVoto(Integer notaVoto) {
		this.notaVoto = notaVoto;
	}

	public boolean isVotou() {
		return votou;
	}

	public void setVotou(boolean votou) {
		this.votou = votou;
	}

	public Comentario getComentario() {
		return comentario;
	}

	public void setComentario(Comentario comentario) {
		this.comentario = comentario;
	}

	public long getIdFilme() {
		return idFilme;
	}

	public void setIdFilme(long idFilme) {
		this.idFilme = idFilme;
	}

	public String getComentarioFilme() {
		return comentarioFilme;
	}

	public void setComentarioFilme(String comentarioFilme) {
		this.comentarioFilme = comentarioFilme;
	}

	public List<Comentario> getListaComentariosFilme() {
		return listaComentariosFilme;
	}

	public void setListaComentariosFilme(List<Comentario> listaComentariosFilme) {
		this.listaComentariosFilme = listaComentariosFilme;
	}
}
